//= require Sortable.min
//= require canvas-to-blob.min

(function(global) {
  'use strict';

  // Sets callbacks for toggling checkboxes
  function applyCheckboxCallBack()  {
    $("[data-action='check-item']").off().on('click', function(e){
      var checkboxitem = $(this).find("input");
      var checked = checkboxitem.is(":checked");
      $.ajax({
        url: checkboxitem.data("link-url"),
        type: "POST",
        dataType: "json",
        data: {checklistitem_id: checkboxitem.data("id"), checked: checked},
        success: function (data) {
          checkboxitem.prop("checked", checked);
        },
        error: function (data) {
          checkboxitem.prop("checked", !checked);
        }
      });
    });
  }

  // Sets callback for completing/uncompleting step
  function applyStepCompletedCallBack() {
    // First, remove old event handlers, as we use turbolinks
    $("[data-action='complete-step'], [data-action='uncomplete-step']")
    .off().on('click', function(e){
      var button = $(this);
      var step = $(this).parents(".step");
      var completed = !step.hasClass("completed");

      $.ajax({
        url: button.data("link-url"),
        type: "POST",
        dataType: "json",
        data: {completed: completed},
        success: function (data) {
          step.toggleClass("completed");
          step.find(".toggle-step-complete[data-action='complete-step']").toggleClass('hidden');
          step.find(".toggle-step-complete[data-action='uncomplete-step']").toggleClass('hidden');
          step.find(".button-step-complete[data-action='complete-step']").toggleClass('hidden');
          step.find(".button-step-complete[data-action='uncomplete-step']").toggleClass('hidden');
        },
        error: function(response) {
          if (response.status === 403) {
            HelperModule.flashAlertMsg(I18n.t('general.no_permissions'), 'danger');
          }
        }
      });
    });
  }

  function applyCancelCallBack() {
    //Click on cancel button
    $("[data-action='cancel-edit']")
    .on("ajax:success", function(e, data) {
      var $form = $(this).closest("form");
      $form.after(data.html);
      var $new_step = $(this).next();
      $(this).remove();

      initCallBacks();
      initHandsOnTable($new_step);
      toggleButtons(true);

      setTimeout(function() {
        initStepsComments();
        SmartAnnotation.preventPropagation('.atwho-user-popover');
        TinyMCE.destroyAll();
        DragNDropSteps.clearFiles();
        MarvinJsEditor.initNewButton('.new-marvinjs-upload-button');
      }, 1000);

    })
    .on("ajax:error", function(e, xhr, status, error) {
      // TODO: error handling
    });
  }

  // Set callback for click on edit button
  function applyEditCallBack() {
    $("[data-action='edit-step']")
    .on("ajax:success", function(e, data) {
      var $step = $(this).closest(".step");
      var $edit_step = $step.after(data.html);
      var $form = $step.next();
      $step.remove();
      formCallback($form);
      initEditableHandsOnTable($form);
      applyCancelCallBack();
      formEditAjax($form);
      toggleButtons(false);
      initializeCheckboxSorting();
      animateSpinner(null, false);
      DragNDropSteps.clearFiles();
      if (tinyMCE.editors.step_description_textarea) tinyMCE.editors.step_description_textarea.remove();
      TinyMCE.init('#step_description_textarea');
      $form.on('change', '.checklist-item-text, .checklist-name', function() {
        $form.addClass(GLOBAL_CONSTANTS.HAS_UNSAVED_DATA_CLASS_NAME);
      });
      $("#new-step-checklists fieldset.nested_step_checklists ul").each(function () {
        enableCheckboxSorting(this);
      });
      $("#step_name").focus();
      $("#new-step-main-tab a").on("shown.bs.tab", function() {
        $("#step_name").focus();
        tinyMCE.editors.step_description_textarea.remove();
        TinyMCE.init('#step_description_textarea');
      });
    })
    .on("ajax:error", function(e, response) {
      if (response.status === 403) {
          HelperModule.flashAlertMsg(I18n.t('general.no_permissions'), 'danger');
      }
    });
  }

  // Set callback for click on move step
  function applyMoveStepCallBack() {
    $('#steps').on('ajax:success', "[data-action='move-step']", function(e, data) {
      if ($.isEmptyObject(data)) return;

      let $step = $(this).closest('.step');
      let steps = $('#steps').find('.step');
      $('#steps').append($.map(data.steps_order, function(step_data) {
        let step = $('#steps').find(`.step[data-id=${step_data.id}]`);
        step.find('.step-number').html(`${step_data.position + 1}.`);
        return step;
      }));

      $('html, body').animate({ scrollTop: $step.offset().top - window.innerHeight / 2 });

      if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar();
    })
    .on("ajax:error", function(e, xhr) {
      if (xhr.status === 403) {
        HelperModule.flashAlertMsg(I18n.t('general.no_permissions'), 'danger');
      }
    });
  }

  function formCallback($form) {
    $form
    .on("fields_added.nested_form_fields", function(e, param) {
      if (param.object_class == "table") {
        initEditableHandsOnTable($form);
      }
    })
    .on("fields_removed.nested_form_fields", function(e, param) {
      if (param.object_class == "asset") {
        // Clear file input
        $(e.target).find("input[type='file']").val("");
      }
    });
  }

    // Init ajax success/error for edit form
  function formEditAjax($form) {
    $form
    .on("ajax:beforeSend", function () {
      $(".nested_step_checklists ul").each(function () {
        reorderCheckboxData(this);
      });
    })
    .on("ajax:success", function(e, data) {
      $(this).after(data.html);
      var $new_step = $(this).next();
      $(this).remove();

      initCallBacks();
      initHandsOnTable($new_step);
      toggleButtons(true);
      TinyMCE.destroyAll();
      SmartAnnotation.preventPropagation('.atwho-user-popover');
      // Show the edited step
      $new_step.find(".panel-collapse:first").addClass("collapse in");

      //Rerender tables
      $new_step.find("[data-role='step-hot-table']").each(function() {
        renderTable($(this));
      });
    })
    .on("ajax:error", function(e, xhr, status, error) {
      $form.renderFormErrors('step', xhr.responseJSON, true, e);

      formCallback($form);
      initEditableHandsOnTable($form);
      applyCancelCallBack();

      SmartAnnotation.preventPropagation('.atwho-user-popover');

      //Rerender tables
      $form.find("[data-role='step-hot-table']").each(function() {
        renderTable($(this));
      });
    });
  }

  function toggleButtons(show) {
    if (show) {
      $("[data-action='new-step']").show();
      $("[data-action='edit-step']").show();
      if ($('#steps .step').length > 0) {
        $(".expand-all-steps").show();
      }
    } else {
      $("[data-action='new-step']").hide();
      $("[data-action='edit-step']").hide();
    }
  }

  // Creates handsontable where needed
  function initHandsOnTable(root) {
    root.find("[data-role='hot-table']").each(function()  {
      var $container = $(this).find("[data-role='step-hot-table']");
      var contents = $(this).find('.hot-contents');

      $container.handsontable({
        startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>,
        startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>,
        rowHeaders: true,
        colHeaders: true,
        fillHandle: false,
        formulas: true,
        cells: function (row, col, prop) {
          var cellProperties = {};

          if (col >= 0)
            cellProperties.readOnly = true;
          else
            cellProperties.readOnly = false;

          return cellProperties;
        }
      });
      var hot = $container.handsontable('getInstance');

      if (contents.attr("value")) {
        var data = JSON.parse(contents.attr("value"));
        if (Array.isArray(data.data)) hot.loadData(data.data);
        setTimeout(() => {
          hot.render()
        }, 0)
      }
    });
  }

  // Init handsontable which can be edited
  function initEditableHandsOnTable(root) {
    root.find("[data-role='editable-table']").each(function() {
      var $container = $(this).find(".hot");

      if ($container.is("[initialized]")) {
        return true;
      }

      var contents = $(this).find('.hot-contents');
      var data = null;
      if (contents.attr("value")) {
        data = JSON.parse(contents.attr("value")).data;
      }
      if ($container.is(":visible")) {
        $(this).css("width", $("#new-step-tables").css("width"));
      }

      $container.handsontable({
        data: data,
        startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>,
        startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>,
        minRows: 1,
        minCols: 1,
        rowHeaders: true,
        colHeaders: true,
        contextMenu: true,
        formulas: true,
        preventOverflow: 'horizontal',
        afterChange: function() {
          $container.addClass(GLOBAL_CONSTANTS.HAS_UNSAVED_DATA_CLASS_NAME);
        }
      });

      $container.attr("initialized", true);
      renderTable($container);
    });

    $("#new-step-tables-tab a")
    .on("shown.bs.tab", function() {
      $(this).parents("form").find("div.hot").each(function()  {
        $(this).parent().css("width", $("#new-step-tables").css("width"));
        renderTable($(this));
      });
    });
  }

  function applyCancelOnNew() {
    $("[data-action='cancel-new']").click(function(event) {
      event.preventDefault();
      event.stopPropagation();
      event.stopImmediatePropagation();
      var $form = $(this).closest("form");
      $form.parent().remove().promise().done(function() {
        newStepHandler();
      });
      toggleButtons(true);
      DragNDropSteps.clearFiles();

      tinyMCE.editors.step_description_textarea.remove();
    });
  }

  function initDeleteStep(){
    $("[data-action='delete-step']").on("confirm:complete", function (e, answer) {
      if (answer) {
        animateLoading();
      }
    });
  }

  function initCallBacks() {
    if (typeof(applyCreateWopiFileCallback) === 'function') applyCreateWopiFileCallback();
    applyCheckboxCallBack();
    applyStepCompletedCallBack();
    applyEditCallBack();
    applyMoveStepCallBack();
    initDeleteStep();
    TinyMCE.highlight();
  }

  /*
   * Correction for sorting with "Sortable.min" JS library to work correctly with
   * "nested_form_fields" gem.
   */
  function reorderCheckboxData(checkboxUl) {
    // Make sure checkbox item insertion script is always at the bottom of "ul"
    // tag, otherwise item will not be inserted at bottom
    if(!$(checkboxUl).children().last().is('script')) {
      $(checkboxUl).find("script").appendTo(checkboxUl);
    }

    var $checkboxes = $(checkboxUl).find(".nested_fields");
    $checkboxes.each(function (itemPos) {
      var $this = $(this);
      var $formGroup = $this.find(".form-group");
      var $label = $formGroup.find(".control-label");
      var $textInput = $formGroup.find(".checklist-item-text");
      var $posInput = $formGroup.parent().find(".checklist-item-pos");
      var $destroyLink = $this.find(".remove_nested_fields_link");

      var labelFor = $label.attr("for");
      var textName = $textInput.attr("name");
      var textId = $textInput.attr("id");
      var posName = $posInput.attr("name");
      var posId = $posInput.attr("id");
      var destroyLink = $destroyLink.attr("data-delete-association-field-name");

      labelFor = labelFor.replace(/\d+_text/, itemPos + "_text");
      textName = textName.replace(/\[\d+\]\[text\]/, "[" + itemPos + "][text]");
      textId = textId.replace(/\d+_text/, itemPos + "_text");
      posName = posName.replace(/\[\d+\]\[position\]/, "[" + itemPos + "][position]");
      posId = posId.replace(/\d+_position/, itemPos + "_position");
      destroyLink = destroyLink.replace(/\[\d+\]\[_destroy\]/, "[" + itemPos + "][_destroy]");

      $label.attr("for", labelFor);
      $textInput.attr("name", textName); // Actually needed for sorting to work
      $textInput.attr("id", textId);
      $posInput.attr("name", posName);
      $posInput.attr("id", posId);
      $posInput.val(itemPos);
      $destroyLink.attr("data-delete-association-field-name", destroyLink);

      var $idInput = $this.find("> input");
      if ($idInput.length) {
        var idName = $idInput.attr("name");
        var idId = $idInput.attr("id");

        idName = idName.replace(/\[\d+\]\[id\]/, "[" + itemPos + "][id]");
        idId = idId.replace(/\d+_id/, itemPos + "_id");

        $idInput.attr("name", idName);
        $idInput.attr("id", idId);
      }

      if ($this.css('display') == 'none') {
        // Actually needed for deleting to work
        var $destroyInput = $this.prev();
        var destroyName = $destroyInput.attr("name");
        destroyName = destroyName.replace(/\[\d+\]\[_destroy\]/, "[" + itemPos + "][_destroy]");
        $destroyInput.attr("name", destroyName);
      }

      $formGroup.addClass(GLOBAL_CONSTANTS.HAS_UNSAVED_DATA_CLASS_NAME);
    });
  }

  function enableCheckboxSorting(el) {
    Sortable.create(el, {
      draggable: 'fieldset',
      handle: '.fa-circle',
      onUpdate: function () {
        reorderCheckboxData(el);
      }
    });
  }

  function initializeCheckboxSorting() {
    var el = $("#new-step-checklists a[data-association-path=step_checklists]");

    el.click(function () {
      // calling code below must be defered because at this step HTML is not
      // inserted into DOM.
      setTimeout(function () {
        var list = el.parent().find("fieldset.nested_step_checklists:last ul");
        enableCheckboxSorting(list.get(0));
      });
    });
  }

  // New step AJAX
  function newStepHandler() {
    $("[data-action='new-step']").off().on('click', function(event) {
      event.preventDefault();
      event.stopPropagation();
      event.stopImmediatePropagation();
      var $btn = $(this);
      $btn.off();
      animateSpinner(null, true);
      $('#protocol-container').collapse('show');

      $.ajax({
        url: $btn.data('href'),
        method: 'GET',
        success: function(data) {
          var $form = $(data.html);
          $('#steps').append($form).promise().done(function() {
            animateSpinner(null, false);
            // Scroll to bottom
            $('html, body').animate({
              scrollTop: $(document).height() - $(window).height()
            });
            formCallback($form);
            applyCancelOnNew();
            toggleButtons(false);
            initializeCheckboxSorting();

            $('#step_name').focus();
            $('#new-step-main-tab a')
              .on('shown.bs.tab', function() {
                $('#step_name').focus();
                tinyMCE.editors.step_description_textarea.remove();
                TinyMCE.init('#step_description_textarea');
              })

            TinyMCE.init('#step_description_textarea');
          });

        },
        error: function(response) {
          if (response.status === 403) {
            HelperModule.flashAlertMsg(I18n.t('general.no_permissions'), 'danger');
            animateSpinner(null, false);
          }
        }
      })
    });
  }

  // Needed because server-side validation failure clears locations of
  // files to be uploaded and checklist's items etc. Also user
  // experience is improved
  global.processStep = function processStep(ev, editMode) {
    ev.stopPropagation();
    ev.preventDefault();
    ev.stopImmediatePropagation();

    var $form = $(ev.target.form);
    $form.clearFormErrors();
    $form.removeBlankFileForms();

    var $checklists = $form.find(".nested_step_checklists");
    var checklistsValid = checklistsValidator(ev, $checklists, editMode);
    var $nameInput = $form.find("#step_name");
    var nameValid = textValidator(ev, $nameInput, 1,
      <%= Constants::NAME_MAX_LENGTH %>);
    var $descrTextarea = $form.find("#step_description_textarea");
    var $tinyMCEInput = tinyMCE.editors.step_description_textarea.getContent();
    var descriptionValid = textValidator(ev, $descrTextarea, 0,
      <%= Constants::RICH_TEXT_MAX_LENGTH %>, false, $tinyMCEInput);
    var tableNamesValidArray = [];
    // iterate over table titles and validate their length
    $form.find(".table_name").each(function(index , tableName) {
      if (tableName.value.length > 0) {
        tableNamesValidArray[index] = textValidator(ev, tableName, 1,
          <%= Constants::NAME_MAX_LENGTH %> );
      } else {
        tableNamesValidArray[index] = true;
      }
    });
    var tableNamesValid = true;
    // passes if all table names are valid
    for (var i=0;i<tableNamesValidArray.length;i++){
      if(tableNamesValidArray[i] !== true){
        tableNamesValid = false;
        break;
      }
    }
    if (DragNDropSteps.filesStatus() &&
        checklistsValid &&
        nameValid &&
        descriptionValid &&
        tableNamesValid ) {

      $form.find("[data-role='editable-table']").each(function() {
        let hot = $(this).find(".hot").handsontable('getInstance');
        let contents = $(this).find('.hot-contents');
        let tableData = JSON.stringify({data: hot.getData()});
        contents.attr("value", tableData);
      });

      setTimeout(function() {
        initStepsComments();
        SmartAnnotation.preventPropagation('.atwho-user-popover');
      }, 1000);

      animateSpinner(null, true);

      $(".nested_step_checklists ul").each(function () {
        reorderCheckboxData(this);
      });

      DragNDropSteps.appendFilesToForm(ev).then(formData => {
        formData.append('step[description]', $tinyMCEInput);
        $.ajax({
          url: $form.attr('action'),
          method: 'POST',
          data: formData,
          contentType: false,
          processData: false,
          success: function(data) {
            $($form.closest('.well')).after(data.html);
            var $new_step = $($form.closest('.well')).next();
            $($form.closest('.well')).remove();

            initCallBacks();
            initHandsOnTable($new_step);
            expandStep($new_step);
            toggleButtons(true);
            SmartAnnotation.preventPropagation('.atwho-user-popover');
            $new_step.find('.attachments').trigger('reorder');
            tinyMCE.editors.step_description_textarea.remove();
            MarvinJsEditor.initNewButton('.new-marvinjs-upload-button');

            //Rerender tables
            $new_step.find("div.step-result-hot-table").each(function()  {
              $(this).handsontable("render");
            });
            animateSpinner(null, false);
            DragNDropSteps.clearFiles();
            if (typeof refreshProtocolStatusBar === 'function') refreshProtocolStatusBar();
          },
          error: function(xhr) {
            if (xhr.responseJSON['assets.file']) {
              $('#new-step-assets-group').addClass('has-error');
              $('#new-step-assets-tab').addClass('has-error');
              $.each(xhr.responseJSON['assets.file'], function(_, value) {
                 $('#new-step-assets-group').prepend('<span class="help-block">' + value + '</span>');
              });
            }
            animateSpinner(null, false);
            SmartAnnotation.preventPropagation('.atwho-user-popover');
          }
        });
        newStepHandler();
      }).catch(() => {
        $('#new-step-assets-tab').addClass('has-error');
        $('#new-step-assets-group')
          .addClass('has-error')
          .prepend('<span class="help-block">' +  I18n.t('general.file.upload_failure') + '</span>');
        animateSpinner(null, false);
      });
    }
  }

  // Expand all steps
  function expandAllSteps() {
    $('.step .panel-collapse').collapse('show');
    $(document).find("[data-role='step-hot-table']").each(function()  {
      renderTable($(this));
    });
  }

  function expandStep(step) {
    $('.panel-collapse', step).collapse('show');
    $(step).find("div.step-result-hot-table").each(function()  {
      renderTable($(this));
    });
  }

  function renderTable(table) {
    $(table).handsontable("render");
    // Yet another dirty hack to solve HandsOnTable problems
    if (parseInt($(table).css('height'), 10) < parseInt($(table).css('max-height'), 10) - 30) {
      $(table).find('.ht_master .wtHolder').css({ 'height': '100%',
                                                  'width': '100%' });
    }
  }

  function initStepsComments() {
    Comments.init();
  }

    // On init
  initCallBacks();
  initHandsOnTable($(document));
  expandAllSteps();
  TinyMCE.highlight();
  SmartAnnotation.preventPropagation('.atwho-user-popover');
  newStepHandler();

  $(function () {
    $("[data-action='collapse-steps']").click(function () {
      $('.step .panel-collapse').collapse('hide');
    });
    $("[data-action='expand-steps']").click(expandAllSteps);
  });

  global.initHandsOnTable = initHandsOnTable;
})(window);

(function() {
    // Reorder attachments
  function reorderAttachmentsInit() {
    $('#steps').on('click', '.attachments-actions .change-order', function(e){
      var orderDropdown = $(this).closest('.dropdown-menu');
      var assetsContainer = $(`.attachments[data-step-id=${orderDropdown.data('step-id')}]`)
      var order = $(this).data('order');
      e.preventDefault();
      assetsContainer.data('order', order);
      orderDropdown.find('.change-order').removeClass('selected');
      $(this).addClass('selected');
      assetsContainer.trigger('reorder');
      $.post(orderDropdown.data('state-save-url'), {
        assets: { order: order }
      });
    })

    $('#steps').on('reorder', '.attachments', function() {
      var assets = $(`.attachments[data-step-id=${$(this).data('step-id')}] .asset`);
      var order = $(this).data('order');
      var sortedAssets = assets.sort(function(a, b) {
        if (a.dataset.assetOrder == b.dataset.assetOrder) {
          if (order == 'new') {
            return b.dataset.assetUpdatedAt - a.dataset.assetUpdatedAt;
          } if (order == 'old') {
            return a.dataset.assetUpdatedAt - b.dataset.assetUpdatedAt;
          } if (order == 'atoz') {
            return a.dataset.assetFileName.toLowerCase() > b.dataset.assetFileName.toLowerCase() ? 1 : -1;
          } if (order == 'ztoa') {
            return b.dataset.assetFileName.toLowerCase() > a.dataset.assetFileName.toLowerCase() ? 1 : -1;
          }
        }

        return a.dataset.assetOrder > b.dataset.assetOrder ? 1 : -1
      })

      $.each(sortedAssets, function(i, element){
        element.style.order = i
      })
    })
    .on('DOMSubtreeModified', '.attachments', function() {
      $(this).trigger('reorder');
    })
    $('.attachments').trigger('reorder');
  }

  function initAssetViewModeToggle(){
    $('#steps').on('click', '.attachments-actions .attachments-view-mode', function () {
      var viewModeBtn = $(this);
      $.post(viewModeBtn.closest('.dropdown-menu').data('view-mode-url'), {
        assets_view_mode: viewModeBtn.data('assets-view-mode')
      }, function(result) {
        viewModeBtn.closest('.dropdown-menu').find('.attachments-view-mode').removeClass('selected');
        viewModeBtn.addClass('selected');
        viewModeBtn.closest('.step').find('.attachments').html(result.html)
      })
    })
  }

  reorderAttachmentsInit();
  initAssetViewModeToggle();
})();
